﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ScriptManager.Data.Base;
using ScriptManager.Data.BusinessObjects;
using ScriptManager.Data.ManagerObjects;

namespace ScriptManager.Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Out.WriteLine("Press enter to start Example One");
            Console.In.ReadLine();
            ExampleOne();

            Console.Out.WriteLine("Press enter to start Example Two");
            Console.In.ReadLine();
            //ExampleTwoA();
            //ExampleTwoB();
        }

        static void ExampleOne()
        {
            IManagerFactory managerFactory = new ManagerFactory();
            IProductManager productManager = managerFactory.GetProductManager();
            ICategoryManager categoryManager = managerFactory.GetCategoryManager();

            //// get Product from DB
            //Product product = productManager.GetById("BY-02");
            //if (product == null)
            //    throw new NullReferenceException();

            //Console.Out.WriteLine("Existing Values: {0}, {1}", product.Name, product.Descn);
            //// NHibernate's associateve mapping is awesome.
            //Console.Out.WriteLine("Associated Values: {0}, {1}", product.Category.Name, product.Category);

            //string name = product.Name;
            //string description = product.Descn;

            /* As the Transaction spans the name change and then the reverse of it, no changes are actually
             * preserved in the DB
             * */

            //productManager.Session.BeginTransaction();

            //product.Name = "Oswald Cobblepot";
            //product.Descn = "A great villian.";
            //productManager.Session.CommitChanges();

            //product.Name = name;
            //product.Descn = description;
            //productManager.Session.CommitChanges();

            //productManager.Session.CommitTransaction();

            //Following is an example of chaining data requests based on selected criteria

            foreach (var item in categoryManager.GetAll())
            {
                Console.Out.WriteLine("Category ID: {0}, Category Name {1}", item.Id, item.Name);
            }

            Console.Out.WriteLine("Please enter a categoryID, then press enter to continue.");
            string categoryID = Console.In.ReadLine();

            if (categoryID == null)
                    throw new NullReferenceException();

            Console.Out.WriteLine("");
            Console.Out.WriteLine("Products in this Category");
            Console.Out.WriteLine("");

            foreach (var item in productManager.GetByCategoryId(categoryManager.GetById(categoryID).Name))
            {
                Console.Out.WriteLine("{0}", item.Name);
                Console.Out.WriteLine("Product Items: ");

                foreach (Item aItem in item.Items)
                {
                    Console.Out.WriteLine("     {0}", aItem.Name);
                }
            }
        }

        static void ExampleTwoA()
        {
            // Get default session from the NHibernateSessionManager singleton.
            // (This session will be unique for each thread or HttpContext.)
            INHibernateSession session = NHibernateSessionManager.Instance.Session;
            Console.Out.WriteLine("Both Managers will be using the same Session.");
            ExampleTwo(session);
        }

        static void ExampleTwoB()
        {
            //Craete a new session.
            INHibernateSession session = NHibernateSessionManager.Instance.CreateSession();
            Console.Out.WriteLine("The Managers will be using different sessions.");
            ExampleTwo(session);
        }

        static void ExampleTwo(INHibernateSession session)
        {
            /*Clearly this is the factory Pattern*/
            IManagerFactory managerFactory = new ManagerFactory();

            /*Using the Singleton pattern (this will usually be a static method)*/
            // Created with the default session from the NhibernateSessionManager singleton.
            IProductManager productManager = managerFactory.GetProductManager();

            /*THIS IS IoC (Inversion of Control) This is becuase GetCategoryManager does not control 
             * the session, it is just able to use one passed into it. This would be like in delphi
             * when you have a unit, but rather than give the unit direct access to the DM, you pass in
             * it to the unit.
             **/
            // created with the session passed in.
            ICategoryManager categoryManager = managerFactory.GetCategoryManager(session);

            Product product = productManager.GetById("BD-01");
            Category category = categoryManager.GetById("BIRDS");

            //Save original value.
            string productName = product.Name;

            //Change product name.
            product.Name = "LOOK, I CHANGED!";
            //Commit CategoryManager changes.
            categoryManager.Session.CommitChanges();

            Console.Out.WriteLine("Did the product's name change? Press enger to continue.");
            Console.In.ReadLine();

            //Restore value.
            product.Name = productName;
            productManager.Session.CommitChanges();
        }

    }
}
